package main

import "fmt"

func main() {
	test1()
	// test2()
	// test3()
	// test4()
	// test5()
	// test6()
	// test7()
	// test8()
	//test10()
	//test11()
}

// 认识slice
func test1() {
	slice1 := make([]int, 3)
	for _, s := range slice1 {
		fmt.Println(s)
	}
	slice1 = append(slice1, 1)
	for _, s := range slice1 {
		fmt.Println(s)
	}
}

// 切片操作
func test2() {
	slice := []int{1, 2, 3}
	fmt.Println(slice)

	// 这里声明了一个slice int类型的数组切片
	// 切片的长度是可变的，我们可以通过append方法向里面添加同类型的值
	slice = append(slice, 4, 5, 6)
	fmt.Println(slice)
}

// 证明数组是值传递(值拷贝) ，切片是引用传递
func test3() {
	// 数组
	var arr1 = [3]int{1, 2, 3}
	fmt.Println(arr1) // [1,2,3]
	var arr2 = arr1
	fmt.Println(arr2) // [1,2,3]
	arr2[0] = -1
	fmt.Println(arr1) // [1,2,3]
	fmt.Println(arr2) // [-1,2,3]

	fmt.Println("----------")
	// 切片
	var slice1 = []int{1, 2, 3}
	fmt.Println(slice1) // [1 2 3]
	var slice2 = slice1
	fmt.Println(slice2) // [1 2 3]
	slice2[0] = -1
	fmt.Println(slice1) // [-1 2 3]
	fmt.Println(slice2) // [-1 2 3]

}

// 简单切片表达式
// 切片的底层就是一个数组，所以我们可以基于数组通过切片表达式得到切片。
// 切片表达式中的low和high表示一个索引范围（左包含，右不包含），
// 也就是下面代码中从数组a中选出1<=索引值<4的元素组成切片s，
// 得到的切片长度=high-low，容量等于得到的切片的底层数组的容量。
func test4() {
	a := [5]int{1, 2, 3, 4, 5}
	s := a[1:3] // s := a[low:high]
	fmt.Printf("s:%v len(s):%v cap(s):%v\n", s, len(s), cap(s))
	// result ==> s:[2 3] len(s):2 cap(s):4

	// a[2:]  // 等同于 a[2:len(a)]
	// a[:3]  // 等同于 a[0:3]
	// a[:]   // 等同于 a[0:len(a)]
}

// 切片使用
func test5() {
	a := [5]int{1, 2, 3, 4, 5}
	s := a[1:3] // s := a[low:high]
	fmt.Printf("s:%v len(s):%v cap(s):%v\n", s, len(s), cap(s))
	s2 := s[3:4] // 索引的上限是cap(s)而不是len(s)
	fmt.Printf("s2:%v len(s2):%v cap(s2):%v\n", s2, len(s2), cap(s2))
}

// 使用make创建切片
func test6() {
	slice := make([]int, 2, 10)
	fmt.Println(slice)
	fmt.Println(len(slice))
	fmt.Println(cap(slice))

	slice2 := make([]string, 2, 10)
	fmt.Println(slice2)
	fmt.Println(len(slice2))
	fmt.Println(cap(slice2))
}

// 扩容是按照老的容量乘以2
func test7() {
	var slice []int
	for i := 0; i < 10; i++ {
		slice = append(slice, i)
		fmt.Printf("%v  len:%d  cap:%d  ptr:%p\n", slice, len(slice), cap(slice), slice)
	}
}

// 为了解决引用传递的问题，可以使用copy（）函数，深拷贝
func test8() {
	slice := []int{1, 2, 3}

	slice2 := make([]int, 5, 5)
	copy(slice2, slice)

	slice2[0] = -1
	fmt.Println(slice)
	fmt.Println(slice2)
}

//1.不同类型的切片无法复制
//2.如果s1的长度大于s2的长度，将s2中对应位置上的值替换s1中对应位置的值
//3.如果s1的长度小于s2的长度，多余的将不做替换

func test9() {
	s1 := []int{1, 2, 3}
	s2 := []int{4, 5}
	s3 := []int{6, 7, 8, 9}
	copy(s1, s2)
	fmt.Println(s1) //[4 5 3]
	copy(s2, s3)
	fmt.Println(s2) //[6 7]
}

func test10() {
	var a = make([]int, 5, 10)
	for i := 0; i < 10; i++ {
		a = append(a, i)
	}
	fmt.Println(a)
	fmt.Println(len(a))
	fmt.Println(cap(a))
}
func test11() {
	sliceList := make([]map[string]string, 5)
	for i := range sliceList {
		sliceList[i] = make(map[string]string, 1)
		sliceList[i]["1"] = "1"
	}
	fmt.Printf("Version A: Value of items: %v\n", sliceList)
}
